//----------------------------------------------------------------------------
//  ,-.
// /_\___ ,   Ninja Framework
// '  ___\    (C) Riccardo Capra - http://riccar.do
//  //   \\
//----------------------------------------------------------------------------
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------------

#ifndef NJ_HIGH_RESOLUTION_TIMER_H
#	define NJ_HIGH_RESOLUTION_TIMER_H

#	include "NjExample01.h"

	/// \brief A platform specific high resolution timer
	class NjHighResolutionTimer
	{
	public:
		NJ_TRIVIAL_DESTRUCTOR(NjHighResolutionTimer);

		/// \brief The type used to measure time in a custom Tick unit measure
		typedef NjUint64 TimeTick;

		/// \brief Creates a NjHighResolutionTimer
		///
		/// Is is set to 0 in paused state
		NjHighResolutionTimer();

		/// \brief Creates a NjHighResolutionTimer
		///
		/// The state is copied from \em kCopy
		NjHighResolutionTimer(NjHighResolutionTimer const & kCopy);


		/// \brief Copies the state from \em kCopy
		NjHighResolutionTimer & operator=(NjHighResolutionTimer const & kCopy);

		/// \brief Returns NJ_FALSE if is set to 0 and is in paused state, NJ_TRUE otherwise
		operator NjBool() const;

		/// \brief Returns NJ_TRUE if is set to 0 and is in paused state, NJ_FALSE otherwise
		NjBool operator!() const;

		/// \brief Returns NJ_TRUE if is in the exact same state of \em kRightValue
		NjBool operator==(NjHighResolutionTimer const & kRightValue) const;

		/// \brief Returns NJ_FALSE if is in the exact same state of \em kRightValue
		NjBool operator!=(NjHighResolutionTimer const & kRightValue) const;

		/// \brief Starts running
		void Start();

		/// \brief Stops running
		void Pause();

		/// \brief Reset to 0
		///
		/// If it's running it will continue running, otherwise it will continue staying paused
		void Reset();

		/// \brief Returns the frequency in Hz of TimeTick
		static TimeTick GetTickFrequency();

		/// \brief Returns the current time in TimeTick
		///
		/// The initial value is undefined so just time differences make sense
		static TimeTick GetTick();

		/// \brief Returns the current accumulated time in TimeTick
		///
		/// This can be called both when the timer is paused and when it is running
		TimeTick GetTimeTick();

		/// \brief Returns the current accumulated time in seconds
		NjFloat GetTimeS();

	private:
		/// \brief Private static data
		class Static;
		
		/// \brief Static data initialization
		static void Initialize();

		/// \brief Flag used to store if the internal state is running or not running
		static const NjUint64 FLAG_RUNNING=0x8000000000000000ULL;

		/// \brief Timer state
		NjUint64 m_uTime;

		/// \brief The frequency in Hz of TimeTick
		static NjUint64 ms_uTickFrequency;

		/// \brief The duration in seconds of one TimeTick
		static NjFloat ms_fTickPeriod;
	};

#	include "NjHighResolutionTimer_inline.h"

#endif // NJ_HIGH_RESOLUTION_TIMER_H
